<script setup lang="ts">
import { reactive, watch } from 'vue'
import DetailHeader from '@/components/Layout/DetailHeader/DetailHeader.vue'
import ToolDetail from '@/components/Layout/ToolDetail/ToolDetail.vue'
import { ElMessage } from 'element-plus'

const info = reactive({
  title: "Cron表达式工具",
})

const cronData = reactive({
  expression: '0 0 12 * * ?',
  nextExecutions: [] as string[],
  description: '',
  isValid: true,
  errorMessage: ''
})

// 可视化生成器配置
const generator = reactive({
  second: {
    type: 'every', // every, specific, range, step
    value: 0,
    start: 0,
    end: 59,
    step: 1,
    specific: [] as number[]
  },
  minute: {
    type: 'every',
    value: 0,
    start: 0,
    end: 59,
    step: 1,
    specific: [] as number[]
  },
  hour: {
    type: 'every',
    value: 12,
    start: 0,
    end: 23,
    step: 1,
    specific: [] as number[]
  },
  day: {
    type: 'none', // none, step
    value: 1,
    start: 1,
    end: 31,
    step: 1,
    specific: [] as number[]
  },
  week: {
    type: 'none', // none, every
    value: 1,
    start: 1,
    end: 7,
    step: 1,
    specific: [] as number[]
  }
})

// 验证 Cron 表达式
const validateCron = (expression: string) => {
  if (!expression.trim()) {
    cronData.isValid = false
    cronData.errorMessage = '请输入 Cron 表达式'
    return false
  }

  const parts = expression.trim().split(/\s+/)

  if (parts.length !== 6) {
    cronData.isValid = false
    cronData.errorMessage = 'Cron 表达式必须包含 6 个字段（秒 分 时 日 月 周）'
    return false
  }

  // 检查每个字段的基本格式
  const fieldPatterns = [
    /^(\*|\d+|\*\/\d+|\d+-\d+|\d+(,\d+)*|\?)$/, // 秒
    /^(\*|\d+|\*\/\d+|\d+-\d+|\d+(,\d+)*|\?)$/, // 分
    /^(\*|\d+|\*\/\d+|\d+-\d+|\d+(,\d+)*|\?)$/, // 时
    /^(\*|\d+|\*\/\d+|\d+-\d+|\d+(,\d+)*|\?)$/, // 日
    /^(\*|\d+|\*\/\d+|\d+-\d+|\d+(,\d+)*|\?)$/, // 月
    /^(\*|\d+|\*\/\d+|\d+-\d+|\d+(,\d+)*|\?)$/  // 周
  ]

  for (let i = 0; i < 6; i++) {
    if (!fieldPatterns[i].test(parts[i])) {
      cronData.isValid = false
      cronData.errorMessage = `第 ${i + 1} 个字段格式不正确: ${parts[i]}`
      return false
    }
  }

  cronData.isValid = true
  cronData.errorMessage = ''
  return true
}

// 解析 Cron 表达式
const parseCron = (expression: string) => {
  if (!validateCron(expression)) return

  const parts = expression.trim().split(/\s+/)
  const [second, minute, hour, day, , week] = parts

  // 生成描述
  let desc: string[] = []

  // 解析秒
  if (second !== '*') {
    if (second.includes('/')) {
      const [, interval] = second.split('/')
      desc.push(`每${interval}秒`)
    } else if (second.includes('-')) {
      const [start, end] = second.split('-')
      desc.push(`第${start}到${end}秒`)
    } else if (second.includes(',')) {
      desc.push(`第${second}秒`)
    } else {
      desc.push(`第${second}秒`)
    }
  }

  // 解析分
  if (minute !== '*') {
    if (minute.includes('/')) {
      const [, interval] = minute.split('/')
      desc.push(`每${interval}分钟`)
    } else if (minute.includes('-')) {
      const [start, end] = minute.split('-')
      desc.push(`第${start}到${end}分钟`)
    } else if (minute.includes(',')) {
      desc.push(`第${minute}分钟`)
    } else {
      desc.push(`第${minute}分钟`)
    }
  }

  // 解析时
  if (hour !== '*') {
    if (hour.includes('/')) {
      const [, interval] = hour.split('/')
      desc.push(`每${interval}小时`)
    } else if (hour.includes('-')) {
      const [start, end] = hour.split('-')
      desc.push(`${start}点到${end}点`)
    } else if (hour.includes(',')) {
      desc.push(`第${hour}小时`)
    } else {
      desc.push(`第${hour}小时`)
    }
  }

  // 解析日
  if (day !== '*' && day !== '?') {
    if (day.includes('/')) {
      const [, interval] = day.split('/')
      desc.push(`每${interval}天`)
    } else if (day.includes('-')) {
      const [start, end] = day.split('-')
      desc.push(`第${start}到${end}天`)
    } else if (day.includes(',')) {
      desc.push(`第${day}天`)
    } else {
      desc.push(`第${day}天`)
    }
  }



  // 解析周
  if (week !== '*' && week !== '?') {
    if (week.includes('/')) {
      const [, interval] = week.split('/')
      desc.push(`每${interval}周`)
    } else if (week.includes('-')) {
      const [start, end] = week.split('-')
      desc.push(`第${start}到${end}周`)
    } else if (week.includes(',')) {
      desc.push(`第${week}周`)
    } else {
      desc.push(`第${week}周`)
    }
  }

  cronData.description = desc.length > 0 ? desc.join(', ') : '每秒执行'

  // 生成下次执行时间
  generateNextExecutions(parts)
}

// 生成下次执行时间
const generateNextExecutions = (parts: string[]) => {
  const now = new Date()
  cronData.nextExecutions = []

  const [second, minute, hour, day, , week] = parts

  try {
    // 计算下次执行时间
    let nextTime = new Date(now)

    // 设置秒
    if (second !== '*') {
      nextTime.setSeconds(parseInt(second), 0)
    } else {
      nextTime.setSeconds(0, 0)
    }

    // 设置分钟
    if (minute !== '*') {
      if (minute.includes('/')) {
        // 每隔几分钟
        const [, interval] = minute.split('/')
        const minuteInterval = parseInt(interval)
        const currentMinute = now.getMinutes()
        const nextMinute = Math.ceil(currentMinute / minuteInterval) * minuteInterval
        nextTime.setMinutes(nextMinute, nextTime.getSeconds(), 0)
      } else {
        nextTime.setMinutes(parseInt(minute), nextTime.getSeconds(), 0)
      }
    } else {
      nextTime.setMinutes(0, nextTime.getSeconds(), 0)
    }

    // 设置小时
    if (hour !== '*') {
      if (hour.includes('/')) {
        // 每隔几小时
        const [, interval] = hour.split('/')
        const hourInterval = parseInt(interval)
        const currentHour = now.getHours()
        const nextHour = Math.ceil(currentHour / hourInterval) * hourInterval
        nextTime.setHours(nextHour, nextTime.getMinutes(), nextTime.getSeconds(), 0)
      } else {
        nextTime.setHours(parseInt(hour), nextTime.getMinutes(), nextTime.getSeconds(), 0)
      }
    } else {
      nextTime.setHours(0, nextTime.getMinutes(), nextTime.getSeconds(), 0)
    }

    // 设置日期
    if (day !== '*' && day !== '?') {
      if (day.includes('/')) {
        // 每隔几天
        const [, interval] = day.split('/')
        const dayInterval = parseInt(interval)
        const currentDay = now.getDate()
        const nextDay = Math.ceil(currentDay / dayInterval) * dayInterval
        nextTime.setDate(nextDay)
      } else {
        nextTime.setDate(parseInt(day))
      }
    }

    // 设置周
    if (week !== '*' && week !== '?') {
      if (week.includes('/')) {
        // 每隔几周
        const [, interval] = week.split('/')
        const weekInterval = parseInt(interval)
        const currentWeek = now.getDay() || 7
        const targetWeek = parseInt(week)
        let daysToAdd = (targetWeek - currentWeek + 7) % 7
        if (daysToAdd === 0) daysToAdd = 7 * weekInterval
        nextTime.setDate(nextTime.getDate() + daysToAdd)
      } else {
        const targetWeek = parseInt(week)
        const currentWeek = now.getDay() || 7
        let daysToAdd = (targetWeek - currentWeek + 7) % 7
        if (daysToAdd === 0) daysToAdd = 7
        nextTime.setDate(nextTime.getDate() + daysToAdd)
      }
    }

    // 如果时间已过，调整到下一个周期
    if (nextTime <= now) {
      if (minute.includes('/')) {
        // 每隔几分钟的情况
        const [, interval] = minute.split('/')
        const minuteInterval = parseInt(interval)
        nextTime.setMinutes(nextTime.getMinutes() + minuteInterval)
      } else if (hour.includes('/')) {
        // 每隔几小时的情况
        const [, interval] = hour.split('/')
        const hourInterval = parseInt(interval)
        nextTime.setHours(nextTime.getHours() + hourInterval)
      } else if (day !== '*' && day !== '?' && day.includes('/')) {
        // 每隔几天的情况
        const [, interval] = day.split('/')
        const dayInterval = parseInt(interval)
        nextTime.setDate(nextTime.getDate() + dayInterval)
      } else if (week !== '*' && week !== '?') {
        // 每周的情况
        nextTime.setDate(nextTime.getDate() + 7)
      } else {
        // 每天执行的情况
        nextTime.setDate(nextTime.getDate() + 1)
      }
    }

    // 生成未来5次执行时间
    for (let i = 0; i < 5; i++) {
      const next = new Date(nextTime)

      if (minute.includes('/')) {
        // 每隔几分钟
        const [, interval] = minute.split('/')
        const minuteInterval = parseInt(interval)
        next.setMinutes(nextTime.getMinutes() + (i * minuteInterval))
      } else if (hour.includes('/')) {
        // 每隔几小时
        const [, interval] = hour.split('/')
        const hourInterval = parseInt(interval)
        next.setHours(nextTime.getHours() + (i * hourInterval))
      } else if (day !== '*' && day !== '?' && day.includes('/')) {
        // 每隔几天
        const [, interval] = day.split('/')
        const dayInterval = parseInt(interval)
        next.setDate(nextTime.getDate() + (i * dayInterval))
      } else if (week !== '*' && week !== '?') {
        // 每周
        next.setDate(nextTime.getDate() + (i * 7))
      } else {
        // 每天执行
        next.setDate(nextTime.getDate() + i)
      }

      cronData.nextExecutions.push(next.toLocaleString('zh-CN', {
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit'
      }))
    }
  } catch (error) {
    console.error('Cron 计算错误:', error)
    cronData.nextExecutions = ['计算失败，请检查表达式格式']
  }
}

// 生成 Cron 表达式
const generateCron = () => {
  const parts: string[] = []

  // 生成秒
  if (generator.second.type === 'every') {
    parts.push(generator.second.value.toString())
  } else if (generator.second.type === 'step') {
    parts.push(`*/${generator.second.step}`)
  } else {
    parts.push('*')
  }

  // 生成分
  if (generator.minute.type === 'every') {
    parts.push(generator.minute.value.toString())
  } else if (generator.minute.type === 'step') {
    parts.push(`*/${generator.minute.step}`)
  } else {
    parts.push('*')
  }

  // 生成时
  if (generator.hour.type === 'every') {
    parts.push(generator.hour.value.toString())
  } else if (generator.hour.type === 'step') {
    parts.push(`*/${generator.hour.step}`)
  } else {
    parts.push('*')
  }

  // 生成日
  if (generator.day.type === 'step') {
    parts.push(`*/${generator.day.step}`)
  } else {
    parts.push('*')
  }

  // 生成月 - 默认为*
  parts.push('*')

  // 生成周
  if (generator.week.type === 'every') {
    parts.push(generator.week.value.toString())
  } else {
    parts.push('?')
  }

  cronData.expression = parts.join(' ')
  parseCron(cronData.expression)
}

// 复制表达式
const copyExpression = () => {
  navigator.clipboard.writeText(cronData.expression).then(() => {
    ElMessage.success('已复制到剪贴板')
  })
}

// 清空
const clear = () => {
  cronData.expression = ''
  cronData.nextExecutions = []
  cronData.description = ''
  cronData.isValid = true
  cronData.errorMessage = ''
}

// 监听表达式变化
const handleExpressionChange = () => {
  parseCron(cronData.expression)
}

// 监听生成器变化
watch(generator, () => {
  generateCron()
}, { deep: true })

// 初始化
parseCron(cronData.expression)
</script>

<template>
  <div class="flex flex-col mt-3 flex-1">
    <DetailHeader :title="info.title"></DetailHeader>

    <div class="p-4 rounded-2xl bg-white">
      <!-- Cron 表达式输入 -->
      <div class="mb-6">
        <div class="text-lg font-bold mb-2">Cron 表达式</div>
        <div class="flex gap-2 items-end">
          <el-input
            v-model="cronData.expression"
            placeholder="请输入 Cron 表达式，如: 0 0 12 * * ?"
            @input="handleExpressionChange"
            :class="{ 'border-red-500': !cronData.isValid }"
            style="width: 400px;"
          />
          <el-button type="primary" @click="copyExpression">复制</el-button>
          <el-button @click="clear">清空</el-button>
        </div>
        <div v-if="!cronData.isValid" class="text-red-500 text-sm mt-1">
          {{ cronData.errorMessage }}
        </div>
      </div>

      <!-- 可视化生成器 -->
      <div class="mb-6">
        <div class="text-lg font-bold mb-4">可视化生成器</div>
        <div class="grid grid-cols-1 md:grid-cols-5 gap-4">
          <!-- 秒 -->
          <div class="border p-3 rounded">
            <div class="font-bold mb-2 text-sm">秒 (0-59)</div>
            <div class="space-y-2">
              <el-radio-group v-model="generator.second.type" size="small">
                <el-radio label="every">固定</el-radio>
                <el-radio label="step">间隔</el-radio>
              </el-radio-group>
              <div v-if="generator.second.type === 'every'">
                <el-input-number v-model="generator.second.value" :min="0" :max="59" size="small" />
              </div>
              <div v-if="generator.second.type === 'step'">
                <el-input-number v-model="generator.second.step" :min="1" :max="59" size="small" />
              </div>
            </div>
          </div>

          <!-- 分 -->
          <div class="border p-3 rounded">
            <div class="font-bold mb-2 text-sm">分 (0-59)</div>
            <div class="space-y-2">
              <el-radio-group v-model="generator.minute.type" size="small">
                <el-radio label="every">固定</el-radio>
                <el-radio label="step">间隔</el-radio>
              </el-radio-group>
              <div v-if="generator.minute.type === 'every'">
                <el-input-number v-model="generator.minute.value" :min="0" :max="59" size="small" />
              </div>
              <div v-if="generator.minute.type === 'step'">
                <el-input-number v-model="generator.minute.step" :min="1" :max="59" size="small" />
              </div>
            </div>
          </div>

          <!-- 时 -->
          <div class="border p-3 rounded">
            <div class="font-bold mb-2 text-sm">时 (0-23)</div>
            <div class="space-y-2">
              <el-radio-group v-model="generator.hour.type" size="small">
                <el-radio label="every">固定</el-radio>
                <el-radio label="step">间隔</el-radio>
              </el-radio-group>
              <div v-if="generator.hour.type === 'every'">
                <el-input-number v-model="generator.hour.value" :min="0" :max="23" size="small" />
              </div>
              <div v-if="generator.hour.type === 'step'">
                <el-input-number v-model="generator.hour.step" :min="1" :max="23" size="small" />
              </div>
            </div>
          </div>

          <!-- 日 -->
          <div class="border p-3 rounded">
            <div class="font-bold mb-2 text-sm">日 (1-31)</div>
            <div class="space-y-2">
              <el-radio-group v-model="generator.day.type" size="small">
                <el-radio label="none">不指定</el-radio>
                <el-radio label="step">间隔</el-radio>
              </el-radio-group>
              <div v-if="generator.day.type === 'step'">
                <el-input-number v-model="generator.day.step" :min="1" :max="31" size="small" />
              </div>
            </div>
          </div>

          <!-- 周 -->
          <div class="border p-3 rounded">
            <div class="font-bold mb-2 text-sm">周 (1-7)</div>
            <div class="space-y-2">
              <el-radio-group v-model="generator.week.type" size="small">
                <el-radio label="none">不指定</el-radio>
                <el-radio label="every">固定</el-radio>
              </el-radio-group>
              <div v-if="generator.week.type === 'every'">
                <el-input-number v-model="generator.week.value" :min="1" :max="7" size="small" />
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 表达式描述 -->
      <div v-if="cronData.description" class="mb-4">
        <div class="text-lg font-bold mb-2">表达式说明</div>
        <div class="bg-gray-100 p-3 rounded">
          {{ cronData.description }}
        </div>
      </div>

      <!-- 下次执行时间 -->
      <div v-if="cronData.nextExecutions.length > 0" class="mb-4">
        <div class="text-lg font-bold mb-2">下次执行时间</div>
        <div class="bg-gray-100 p-3 rounded">
          <div v-for="(time, index) in cronData.nextExecutions" :key="index" class="mb-1">
            {{ index + 1 }}. {{ time }}
          </div>
        </div>
      </div>

      <!-- 常用表达式 -->
      <div class="mb-4">
        <div class="text-lg font-bold mb-2">常用表达式</div>
        <div class="grid grid-cols-1 md:grid-cols-3 gap-2">
          <el-button @click="cronData.expression = '0 0 12 * * ?'; handleExpressionChange()" size="small">
            每天中午12点
          </el-button>
          <el-button @click="cronData.expression = '0 1 0 * * ?'; handleExpressionChange()" size="small">
            每天凌晨0点1分
          </el-button>
          <el-button @click="cronData.expression = '0 0 9 * * 1'; handleExpressionChange()" size="small">
            每周一上午9点
          </el-button>
          <el-button @click="cronData.expression = '0 */5 * * * ?'; handleExpressionChange()" size="small">
            每隔五分钟执行
          </el-button>
          <el-button @click="cronData.expression = '0 0 */2 * * ?'; handleExpressionChange()" size="small">
            每隔两小时执行
          </el-button>
          <el-button @click="cronData.expression = '0 10 * * * ?'; handleExpressionChange()" size="small">
            每小时的10分执行
          </el-button>
          <el-button @click="cronData.expression = '0 0 6 * * ?'; handleExpressionChange()" size="small">
            每天早晨6点
          </el-button>
          <el-button @click="cronData.expression = '0 30 18 * * ?'; handleExpressionChange()" size="small">
            每天下午6点30分
          </el-button>
          <el-button @click="cronData.expression = '0 0 0 * * 7'; handleExpressionChange()" size="small">
            每周日凌晨
          </el-button>
        </div>
      </div>


    </div>

    <!-- 描述 -->
    <ToolDetail title="描述">
      <el-text>
        Cron 表达式是一个字符串，用来描述定时任务的执行规则。它由 6 个字段组成，从左到右依次是：秒、分、时、日、月、周。<br>
        常用符号说明：<br>
        • * 表示任意值<br>
        • ? 表示不指定值（仅用于日和周字段）<br>
        • / 表示间隔，如 0/15 表示每15秒<br>
        • - 表示范围，如 1-5 表示1到5<br>
        • , 表示多个值，如 1,3,5 表示1、3、5<br>
      </el-text>
    </ToolDetail>
  </div>
</template>

<style scoped>
</style>
